package com.ruoyi.system.service.impl;

import com.rabbitmq.client.Channel;
import com.ruoyi.common.config.RabbitMqConfig;
import com.ruoyi.common.constant.RedisConstants;
import com.ruoyi.common.entity.PaymentCallbackMessage;
import com.ruoyi.common.entity.TransStatusEnum;
import com.ruoyi.system.domain.PaymentCallbackMessageConverter;
import com.ruoyi.system.domain.TbOrder;
import com.ruoyi.system.service.ITbOrderService;
import com.ruoyi.system.websocket.WebSocketPaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;

@Slf4j
@Service
public class PaymentCallbackService {

    @Autowired
    private RedisLockService redisLockService;
    @Autowired
    private ITbOrderService tbOrderService;
    @Autowired
    private WebSocketPaymentService webSocketPaymentService;


    @RabbitListener(queues = RabbitMqConfig.QUEUE_NAME, concurrency = "200", ackMode = "MANUAL")
    public void handlePaymentCallback(PaymentCallbackMessage message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) {
        log.info("--MQ接收到支付回调消息：{}", message);
        String orderId = message.getOrderId();
        String lockKey = RedisConstants.PAYMENT_CALLBACK_LOCK_ + orderId;

        // 尝试获取分布式锁
        if (!redisLockService.tryLock(lockKey)) {
            log.info("订单 {} 的回调正在被其他实例处理。", orderId);
            return;
        }

        try {
            // 处理支付回调逻辑
            if (processPaymentCallback(message)) {
                // 确认消息
                try {
                    channel.basicAck(tag, false);
                } catch (IOException e) {
                    e.printStackTrace();
                    // 如果处理失败，可以选择发送 NACK 或重新投递
                    try {
                        channel.basicNack(tag, false, true);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        } finally {
            // 释放锁
            redisLockService.releaseLock(lockKey);
        }
    }
    @RabbitListener(queues = RabbitMqConfig.PRE_PAYMENT_QUEUE, concurrency = "200", ackMode = "MANUAL")
    public void handleCallback(PaymentCallbackMessage message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) {
        log.info("--MQ接收到预支付消息：{}", message);
        String orderId = message.getOrderId();
        String lockKey = RedisConstants.PAYMENT_PRE_LOCK_ + orderId;

        // 尝试获取分布式锁
        if (!redisLockService.tryLock(lockKey)) {
            log.info("订单 {} 的预支付正在被其他实例处理。", orderId);
            return;
        }
        try {
            // 处理支付回调逻辑
            if (processPaymentPre(message)) {
                // 确认消息
                try {
                    channel.basicAck(tag, false);
                } catch (IOException e) {
                    e.printStackTrace();
                    // 如果处理失败，可以选择发送 NACK 或重新投递
                    try {
                        channel.basicNack(tag, false, true);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        } finally {
            // 释放锁
            redisLockService.releaseLock(lockKey);
        }
    }
    private boolean processPaymentCallback(PaymentCallbackMessage message) {
        // 实际的支付回调处理逻辑
        log.info("正在更新订单 {} 的支付回调", message.getOrderId());
        webSocketPaymentService.handlePaymentNotification(message.getMessageInfo());
        // 更新数据库订单状态 S:成功，W:等待支付，C:退款撤销，R:失败，N:状态未明
        message.setTransStatus(TransStatusEnum.S);
        return tbOrderService.updateTbOrderByOrderId(PaymentCallbackMessageConverter.convertToOrder(message))>0;
    }
    private boolean processPaymentPre(PaymentCallbackMessage message) {
        log.info("正在创建订单 {} 的预支付", message.getOrderId());
        TbOrder order = PaymentCallbackMessageConverter.convertToOrder(message);
        order.setTransAmount(
                order.getTransAmount()
                        .divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP)
        );
        return tbOrderService.insertTbOrder(order)>0;
    }
}
